package com.yuzhihao.writejvm.attributes;

import com.yuzhihao.writejvm.clazz.ClassInfo;
import com.yuzhihao.writejvm.constant.ConstantUtf8Info;
import com.yuzhihao.writejvm.format.ClassFormatEnum;
import com.yuzhihao.writejvm.format.PrintFormat;
import com.yuzhihao.writejvm.read.Parse;
import com.yuzhihao.writejvm.read.ReadClassFileFatory;
import lombok.Data;
import lombok.extern.log4j.Log4j2;

import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 属性
 * <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7">jvmdoc</a>
 *
 * @author yzh
 * @since 2021年12月10日09:54:02
 */

@Data
@Log4j2
public class Attributes implements Parse {

    private ClassFormatEnum cfe_a = ClassFormatEnum.attributes;

    private ClassFormatEnum cfe_ac = ClassFormatEnum.attributes_count;

    protected int attribute_length_u4 = 4;

    protected int attribute_length;

    protected int attribute_name_index_u2 = 2;

    protected String attribute_name;

    private int count;

    private List<Attributes> attributes = new ArrayList<>();

    protected ClassInfo ci;

    public Attributes(){}

    public Attributes(int count){
        this.count = count;
    }

    @Override
    public void parse(DataInputStream dis, ClassInfo ci) {
        this.setCi(ci);
        //是否是直接读取属性长度
        boolean flag = false;
        try {
            if(this.count == 0){
                flag = true;
                this.count = Parse.byteToInt(this.cfe_ac.getB(),dis);
            }

            int i = 0;
            while (i < this.count){
                String attrname = attrname(ci,Parse.byteToInt(this.attribute_name_index_u2,dis));
                Optional.ofNullable(ReadClassFileFatory.attributes_instance(attrname)).ifPresent(e->{
                    e.parse(dis, ci);
                    this.attributes.add(e);
                });
                i++;
            }
        } catch (IOException e) {
            log.error(e);
        }

        if(flag){
            this.out(ci);
        }
    }

    public String print(String print){
        return "";
    }

    /**
     * 获取名称索引对应常量池具体的值
     * @param ci
     * @param ni 索引
     * @return
     */
    private String attrname(ClassInfo ci,int ni){
        ConstantUtf8Info cui = (ConstantUtf8Info)ci.getCp_info().getPools().get(String.valueOf(ni));
        this.attribute_name = cui.getConstant();
        return this.attribute_name;
    }

    public void out(ClassInfo ci) {
        ci.setAttributes_count(this.count);
        ci.setAttribute_info(this);
    }

    protected String stable(String v,String format){
        StringBuilder a = new StringBuilder(v);
        while (a.length() < format.length()){
            a.append(PrintFormat.EMPTY);
        }
        return a.toString();
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append(System.lineSeparator());
        for (Attributes attribute : this.attributes) {
            builder.append(attribute.print(PrintFormat.MEMPTY));
        }
        return builder.toString();
    }
}
